package com.ddc.study.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.StateListDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.ddc.study.R;
import com.ddc.study.util.Log;
import com.ddc.study.util.Utils;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;

/**
 * Created on 2019/11/24.
 *
 * @author lshun
 * @version 1.0
 */
public class ViewPager2Indicator extends LinearLayout {
    private static final String TAG = "ViewPager2Indicator";

    @Nullable
    private ViewPager2 mViewPager2;
    @Nullable
    private RecyclerView.Adapter mAdapter;
    @NonNull
    private final ViewPager2.OnPageChangeCallback mPageChangeCallback = new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            super.onPageScrolled(position, positionOffset, positionOffsetPixels);
        }

        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);
            Log.e(TAG, "onPageSelected -> " + position);
            ViewPager2Indicator.this.onPageSelected(position);
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            super.onPageScrollStateChanged(state);
        }
    };
    @NonNull
    private RecyclerView.AdapterDataObserver mAdapterDataObserver = new RecyclerView.AdapterDataObserver() {
        @Override
        public void onChanged() {
            super.onChanged();
            Log.e(TAG, "onChanged -> ");
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            super.onItemRangeChanged(positionStart, itemCount);
            Log.e(TAG, "onItemRangeChanged -> start = " + positionStart + ", count = " + itemCount);
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
            super.onItemRangeChanged(positionStart, itemCount, payload);
            Log.e(TAG, "onItemRangeChanged -> start = " + positionStart + ", count = " + itemCount);
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            Log.e(TAG, "onItemRangeInserted -> start = " + positionStart + ", count = " + itemCount);
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            super.onItemRangeRemoved(positionStart, itemCount);
            Log.e(TAG, "onItemRangeRemoved -> start = " + positionStart + ", count = " + itemCount);
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            super.onItemRangeMoved(fromPosition, toPosition, itemCount);
            Log.e(TAG, "onItemRangeMoved -> from = " + fromPosition + ", to = " + toPosition + ", count = " + itemCount);
        }
    };

    @Px
    private int mDotSize;
    @Px
    private int mDotMargin;
    @ColorInt
    private int mNormalColor;
    @ColorInt
    private int mSelectedColor;

    private StateListDrawable mDotDrawable;
    private ShapeDrawable mSelectedDrawable, mNormalDrawable;

    private int mSelectPosition = -1;

    public ViewPager2Indicator(Context context) {
        this(context, null);
    }

    public ViewPager2Indicator(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ViewPager2Indicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public ViewPager2Indicator(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ViewPager2Indicator);
        mDotSize = array.getDimensionPixelSize(R.styleable.ViewPager2Indicator_dotSize, Utils.dp2px(getContext(), 6));
        mDotMargin = array.getDimensionPixelSize(R.styleable.ViewPager2Indicator_dotMargin, Utils.dp2px(getContext(), 4));
        mNormalColor = array.getColor(R.styleable.ViewPager2Indicator_normalColor, Color.DKGRAY);
        mSelectedColor = array.getColor(R.styleable.ViewPager2Indicator_selectedColor, Color.WHITE);
        array.recycle();

        mDotDrawable = new StateListDrawable();
        //add selected state drawable
        mSelectedDrawable = new ShapeDrawable(new OvalShape());
        mSelectedDrawable.getPaint().setColor(mSelectedColor);
        mDotDrawable.addState(new int[]{android.R.attr.state_selected}, mSelectedDrawable);
        //add normal state drawable
        mNormalDrawable = new ShapeDrawable(new OvalShape());
        mNormalDrawable.getPaint().setColor(mNormalColor);
        mDotDrawable.addState(new int[]{android.R.attr.state_selected}, mNormalDrawable);
    }

    @Px
    public int getDotSize() {
        return mDotSize;
    }

    public void setDotSize(@Px int dotSize) {
        mDotSize = dotSize;
    }

    @Px
    public int getDotMargin() {
        return mDotMargin;
    }

    public void setDotMargin(@Px int dotMargin) {
        mDotMargin = dotMargin;
    }

    @ColorInt
    public int getNormalColor() {
        return mNormalColor;
    }

    public void setNormalColor(@ColorInt int normalColor) {
        mNormalColor = normalColor;
    }

    @ColorInt
    public int getSelectedColor() {
        return mSelectedColor;
    }

    public void setSelectedColor(@ColorInt int selectedColor) {
        mSelectedColor = selectedColor;
    }

    public void setupWithViewPager2(@Nullable ViewPager2 viewPager2) {
        if (mViewPager2 != null) {
            mViewPager2.unregisterOnPageChangeCallback(mPageChangeCallback);
        }
        if (mAdapter != null) {
            mAdapter.unregisterAdapterDataObserver(mAdapterDataObserver);
        }

        if (viewPager2 == null) {
            mViewPager2 = null;
            mAdapter = null;
            onItemSizeChanged();
        } else {
            mViewPager2 = viewPager2;
            viewPager2.registerOnPageChangeCallback(mPageChangeCallback);
            RecyclerView.Adapter adapter = viewPager2.getAdapter();
            mAdapter = adapter;
            if (adapter != null) {
                adapter.registerAdapterDataObserver(mAdapterDataObserver);
            }
            onItemSizeChanged();
            onPageSelected(viewPager2.getCurrentItem());
        }
    }

    private void onPageSelected(int position) {
        View child = getChildAt(mSelectPosition);
        if (child != null) {
            child.setSelected(false);
        }

        mSelectPosition = position;

        child = getChildAt(position);
        if (child != null) {
            child.setSelected(true);
        }

        invalidate();
    }

    private void onItemSizeChanged() {
        //reset selected view state
        View child = getChildAt(mSelectPosition);
        if (child != null) {
            child.setSelected(false);
        }

        if (mAdapter == null) {
            removeAllViews();
        } else {
            int oldSize = getChildCount();
            int newSize = mAdapter.getItemCount();
            if (oldSize < newSize) {
                for (int i = oldSize; i < newSize; i++) {
                    addView(createDotView());
                }
            } else if (oldSize > newSize) {
                removeViews(0, newSize - oldSize);
            }

            //calculate new position and set selected
            mSelectPosition = mViewPager2 == null ? -1 : mViewPager2.getCurrentItem();
            child = getChildAt(mSelectPosition);
            if (child != null) {
                child.setSelected(true);
            }
        }
    }

    private ImageView createDotView() {
        ImageView imageView = new ImageView(getContext());
        imageView.setImageDrawable(mDotDrawable);
        LayoutParams lp = new LayoutParams(mDotSize, mDotSize);
        lp.setMarginStart(mDotMargin);
        return imageView;
    }
}
